#include "biblioteca.h"

//verifica se em um vetor @material, existe um numero @number de zero ate a posicao @size
int contem(int *material, int size, int number){
    register int i = 0;
    for ( ; i < size; ++i)
        if ( material[i] == number )
            return 1;
    return 0;
}

int populacao_contem_individuo(DP_INDI population, P_INDI indiv, int index){
    register int i  = 0;
    for ( ; i < index; ++i)
        if ( compara_igualdade_individuos(population[i], indiv) )
            return 1;
    return 0;
}

void avaliar_individuo(P_INDI pointer){
    pointer->evaluate = abs((
                                (pointer->sendmory[0] * 1000) + (pointer->sendmory[1] * 100) + (pointer->sendmory[2] * 10) + pointer->sendmory[3] + 
                                ((pointer->sendmory[4] * 1000) + (pointer->sendmory[5] * 100) + (pointer->sendmory[6] * 10) + pointer->sendmory[1])
                                ) - ((pointer->sendmory[4] * 10000) + (pointer->sendmory[5] * 1000) + (pointer->sendmory[2] * 100) + (pointer->sendmory[1] * 10) + pointer->sendmory[7]
                                )
                                );
}

//FUNÇÕES JÁ DECLARADAS

INDI create_individuo_aleatorio(){
    //troca o conteudo das posicoes aleatoriamente
    void shuffle(P_INDI entrada){
        register int i = 0, temp1, temp2;
        for( ; i < SIZE_MATERIAL; ++i){
            temp1 = random()%SIZE_MATERIAL;
            temp2 = entrada->sendmory[i];
            entrada->sendmory[i] = entrada->sendmory[temp1];
            entrada->sendmory[temp1] = temp2;
        }
    }
    INDI retorno;
    register int i = 0;
    for( ; i < SIZE_MATERIAL; ++i)
        retorno.sendmory[i] = i;
    shuffle(&retorno);
    avaliar_individuo(&retorno);
    return retorno;
}

INDI create_individuo_aleatorio_metodo_comum(){
    INDI retorno;
    register int i = 0;
    //para cada posicao do vetor
    for ( ; i < SIZE_MATERIAL; ++i){
        int number;
        //gerar um numero aleatorio que nao esta no vetor
        do{
            number = random() % 10;
        }while( contem(retorno.sendmory, i, number) );
        //preenche a nova posicao
        retorno.sendmory[i] = number;
    }
    avaliar_individuo(&retorno);
    return retorno;
}

INDI create_individuo_com_material(int *sendmory){
    INDI retorno;
    memcpy(retorno.sendmory, sendmory, SIZE_MATERIAL*sizeof(int));
    avaliar_individuo(&retorno);
    return retorno;
}

P_INDI copiar_individuo(P_INDI inicial){
    P_INDI retorno = calloc(1, sizeof(INDI));
    memcpy(retorno, inicial, sizeof(INDI));
    return retorno;
}

P_INDI create_individuo_aleatorio_ponteiro(){
    P_INDI retorno = calloc(1, sizeof(INDI));
    *retorno = create_individuo_aleatorio();
    return retorno;
}

DP_INDI create_population(){
    DP_INDI pop = calloc(SIZE_POP, sizeof(P_INDI));
    register int i = 0;
    for ( ; i < SIZE_POP; ++i){
        pop[i] = create_individuo_aleatorio_ponteiro();
        while( populacao_contem_individuo(pop, pop[i], i) )
            pop[i] = create_individuo_aleatorio_ponteiro();
    }
    return pop;
}

DP_INDI copy_population(DP_INDI pop){
    DP_INDI retorno = calloc(SIZE_POP, sizeof(P_INDI));
    register int i = 0;
    for( ; i < SIZE_POP; ++i)
        retorno[i] = copiar_individuo(pop[i]);
    return retorno;
}

int compara_igualdade_individuos(P_INDI indi1, P_INDI indi2){
    return ( memcmp(indi1->sendmory, indi2->sendmory, SIZE_MATERIAL) == 0 ? 1 : 0 );
}

int compara_avaliacao_individuos_const_void(const void *indi1, const void *indi2){
    P_INDI pi1 = *((DP_INDI) indi1);
    P_INDI pi2 = *((DP_INDI) indi2);
    return ( pi1->evaluate > pi2->evaluate ? 1 : ( pi1->evaluate == pi2->evaluate ? 0 : -1 ) );    
}

void imprime_individuo(P_INDI pointer){
    //register int i = 0;
    printf("S\tE\tN\tD\tM\tO\tR\tY\n\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\nAvaliação: %d\n",pointer->sendmory[0],pointer->sendmory[1],pointer->sendmory[2],pointer->sendmory[3],pointer->sendmory[4],pointer->sendmory[5],pointer->sendmory[6],pointer->sendmory[7], pointer->evaluate);
/*    printf("Individuo:\t[\t");
    for ( ; i < SIZE_MATERIAL; ++i)
        printf("%3d\t",pointer->sendmory[i]);*/
//    printf("]\tAvaliacao: %d\n",pointer->evaluate);
}

void copy_population_to_other(DP_INDI p1, DP_INDI p2, int number){
    register int i = 0;
    for( ; i < number; ++i)
        p2[i] = copiar_individuo(p1[i]);
}

